home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-13
/
emac16ds.zip
/
IBM.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-08-14
|
33KB
|
1,554 lines
;History:1116,1
;Wed Aug 14 22:47:30 1991 restore the screen to whence it came, not one line lower.
;Sat May 04 22:20:32 1991 possible bug in pick_init.
;Sun May 13 23:24:24 1990 Add a "scroll_bar" variable.
;Mon Mar 26 03:22:48 1990 If they enter e0 using the alt-keypad, pretend it's a real key.
;Sun Mar 25 13:07:39 1990 Forgot to set num_screen_cols in monochrome mode.
;Sat Feb 24 20:51:15 1990 M-Escape was M-Esc, which was wrong.
;Thu Jan 11 23:59:48 1990 Only force video mode 3 if there is no memory at b000:0
;Wed Oct 11 22:43:28 1989 When inversing, swap the colors rather than xoring with 77h.
;Sun Sep 24 23:18:42 1989 fix the desqview support.
;Sun Sep 24 23:05:51 1989 reserve a column on the right for the scroll bar.
;Tue Sep 19 23:01:46 1989 add Desqview support.
;Thu Jun 15 23:29:25 1989 Didn't restore port 61h correctly -- crashes a PC.
;Thu Jun 15 00:27:41 1989 clear_count was destroying dx if ibm_cga != 0.
;Sun May 28 00:52:17 1989 Use a different method of testing for enhanced keyboards.
;Sun May 07 00:40:17 1989 Move mouse code from pick.asm to ibm.asm
;Wed May 03 22:15:40 1989 change the arguments to ring_the_bell.
;Wed May 03 21:10:32 1989 'and' the background color with 7 to avoid blinking.
;Tue Mar 07 23:57:47 1989 add parameters to ring_the_bell
;Tue Mar 07 23:46:52 1989 add Jonathan Vail's visual bell code.
;Tue Feb 21 22:20:40 1989 add keypad key support.
;Sat Feb 18 16:57:32 1989 Use hardware cursor positioning for EGA only.
;Fri Feb 17 22:35:11 1989 cleaned up snow-avoidance code a little.
;Mon Jan 30 22:58:16 1989 change the parameters for set_screen_color.
;08-25-88 23:37:09 Create two new keycodes, "C- " and "M- ".
;05-30-88 22:27:44 fix a small problem in save/restore screen
;05-29-88 22:49:48 try getting the attributes from lower left.
;05-29-88 22:42:39 get the attributes from the lower right corner rather than upper right.
;05-27-88 23:25:34 fix a problem in putch where it put garbage characters up.
;05-27-88 00:09:00 read_ibm_cga sometimes gets called with ds=bufseg, not data.
;05-27-88 00:07:02 move_line didn't respect ibm_cga flag--it was always set.
;05-17-88 20:33:20 Add support for hardware scrolls (should work for all displays) [kdb]
;05-17-88 20:02:45 Make move_line wait while reading cga screen [kdb]
;05-17-88 19:35:35 Remove all reference to scrwait function [kdb]
;05-17-88 19:03:22 Macroize scrwait for single char [kdb]
;05-15-88 19:16:51 add scrwait in scrolls [kdb]
;05-15-88 18:58:45 Make move_line wait for each character [kdb]
;05-07-88 22:07:59 implement a swap_screen_flag.
;05-03-88 23:54:55 add more extended keys.
;04-17-88 19:22:28 add some extended keycodes.
;04-16-88 13:13:01 add extended keyboard support.
;04-14-88 22:51:58 If ibm_cga, don't store_debug.
;04-01-88 23:08:28 respond to mouse keys with M-, S-, and C-
;03-31-88 22:02:25 use C-break for the break character (duh)
;03-28-88 19:19:14 just clear the screen on a MDA.
;03-28-88 19:09:19 don't save and restore video memory on an MDA.
;03-28-88 18:28:50 remove block_cursor and under_cursor
;03-26-88 21:59:07 change back to bios calls to read the keyboard.
;03-24-88 00:02:13 add fore_original and back_original.
;02-21-88 12:24:50 make control be bright, meta inverse video.
;02-13-88 18:22:56 use the 18.2 ms timer tick to time the beep.
;02-13-88 16:43:45 don't map Timeout using M-, C-, or S-
;12-07-87 20:07:29 add store_debug
;12-05-87 11:23:35 make the color default to the current color.
;12-05-87 11:20:13 clear the screen on init_entry.
;12-05-87 11:16:53 save dos's screen and restore it when finished.
;07-05-87 22:14:22 caps lock shouldn't apply to M- and C- keys.
page ,132
comment /
Porting EMACS and Percival to MS-DOS computers other than the Z-100:
This entire file (Z-100.ASM) needs to be re-written, since it contains
all the Z-100 dependencies. The following conventions must be maintained:
1) Never leave this module with DF=1.
2) Never destroy ES.
3) Never MOV AX,DATA, always use the copy in the appropriate segment register.
4) Return NC if a routine succeeds, or fulfills its goals.
/
.xlist
include memory.def
data segment byte public
public max_screen_line
max_screen_line db 22 ;number of last text row on screen.
public num_screen_cols
num_screen_cols db ?
db 0 ;in case they access it as a word.
screen_columns db ?
db 0 ;in case they access it as a word.
public fore_original, back_original
fore_original db ?
back_original db ?
public scan_lines_per_char
scan_lines_per_char db 8
public computer_name, computer_name_len
computer_name db 'IBM-PC'
computer_name_len equ $-computer_name
public swap_screen_flag
swap_screen_flag dw 1 ;=1 if we should swap screens.
old_cursor dw ? ;old cursor position from the swapped
; screen.
mouse_flag db ?
mouse_buttons db ?
key_names label byte
db ',','Comma',0
db '(','LPar',0
db ')','RPar',0
db 7fh,'Delete',0
db -1,'Timeout',0
db -2,'Left Down',0 ;mouse button key names.
db -3,'Right Down',0
db -4,'Left Up',0
db -5,'Right Up',0
db -6,'Middle Down',0
db -7,'Middle Up',0
db 0
key_others label byte
db 14,'Back Space',0
db 15,'Tab',0
db 28,'Return',0
db 1,'Escape',0
db 71,'KP7',0 ;Home
db 72,'KP8',0 ;UpArrow
db 73,'KP9',0 ;PgUp
db 74,'KP-',0 ;MMinus
db 75,'KP4',0 ;LeftArrow
db 76,'KP5',0 ;Five
db 77,'KP6',0 ;RightArrow
db 78,'KP+',0 ;MPlus
db 79,'KP1',0 ;End
db 80,'KP2',0 ;DownArrow
db 81,'KP3',0 ;PgDn
db 82,'KP0',0 ;Ins
db 83,'KP.',0 ;Del
db 0
key_special label byte
db 127,'C-Back Space',0
db 10,'C-Return',0
db 0
key_table label byte
; db 0,'000',0
db 1,'M-Escape',0 ;extended
; db 2,'002',0
db 3,'C-@',0
; db 4,'004',0
; db 5,'005',0
; db 6,'006',0
; db 7,'007',0
; db 8,'008',0
; db 9,'009',0
; db 10,'010',0
; db 11,'011',0
; db 12,'012',0
; db 13,'013',0
db 14,'M-Back Space',0 ;extended
db 15,'S-Tab',0
db 16,'M-q',0
db 17,'M-w',0
db 18,'M-e',0
db 19,'M-r',0
db 20,'M-t',0
db 21,'M-y',0
db 22,'M-u',0
db 23,'M-i',0
db 24,'M-o',0
db 25,'M-p',0
db 26,'M-{',0 ;extended
db 27,'M-}',0 ;extended
db 28,'M-Return',0 ;extended
; db 29,'029',0
db 30,'M-a',0
db 31,'M-s',0
db 32,'M-d',0
db 33,'M-f',0
db 34,'M-g',0
db 35,'M-h',0
db 36,'M-j',0
db 37,'M-k',0
db 38,'M-l',0
db 39,'M-;',0 ;extended
db 40,"M-'",0 ;extended
db 41,'M-`',0 ;extended
; db 42,'042',0
db 43,'M-\',0 ;extended
db 44,'M-z',0
db 45,'M-x',0
db 46,'M-c',0
db 47,'M-v',0
db 48,'M-b',0
db 49,'M-n',0
db 50,'M-m',0
db 51,'M-Comma',0 ;extended
db 52,'M-.',0 ;extended
db 53,'M-/',0 ;extended
; db 54,'054',0
db 55,'M-Asterisk',0
; db 56,'056',0
; db 57,'057',0
; db 58,'058',0
db 59,'F1',0
db 60,'F2',0
db 61,'F3',0
db 62,'F4',0
db 63,'F5',0
db 64,'F6',0
db 65,'F7',0
db 66,'F8',0
db 67,'F9',0
db 68,'F10',0
; db 69,'069',0
; db 70,'070',0
db 71,'Home',0
db 72,'Up Arrow',0
db 73,'Pg Up',0
db 74,'M-Minus',0
db 75,'Left Arrow',0
db 76,'Five',0
db 77,'Right Arrow',0
db 78,'M-Plus',0
db 79,'End',0
db 80,'Down Arrow',0
db 81,'Pg Dn',0
db 82,'Ins',0
db 83,'Del',0
db 84,'S-F1',0
db 85,'S-F2',0
db 86,'S-F3',0
db 87,'S-F4',0
db 88,'S-F5',0
db 89,'S-F6',0
db 90,'S-F7',0
db 91,'S-F8',0
db 92,'S-F9',0
db 93,'S-F10',0
db 94,'C-F1',0
db 95,'C-F2',0
db 96,'C-F3',0
db 97,'C-F4',0
db 98,'C-F5',0
db 99,'C-F6',0
db 100,'C-F7',0
db 101,'C-F8',0
db 102,'C-F9',0
db 103,'C-F10',0
db 104,'M-F1',0
db 105,'M-F2',0
db 106,'M-F3',0
db 107,'M-F4',0
db 108,'M-F5',0
db 109,'M-F6',0
db 110,'M-F7',0
db 111,'M-F8',0
db 112,'M-F9',0
db 113,'M-F10',0
db 114,'C-PrtSc',0
db 115,'C-Left Arrow',0
db 116,'C-Right Arrow',0
db 117,'C-End',0
db 118,'C-Pg Dn',0
db 119,'C-Home',0
db 120,'M-1',0
db 121,'M-2',0
db 122,'M-3',0
db 123,'M-4',0
db 124,'M-5',0
db 125,'M-6',0
db 126,'M-7',0
db 127,'M-8',0
db 128,'M-9',0
db 129,'M-0',0
db 130,'M--',0
db 131,'M-=',0
db 132,'C-Pg Up',0
;all of the following are extended.
db 133,'F11',0
db 134,'F12',0
db 135,'S-F11',0
db 136,'S-F12',0
db 137,'C-F11',0
db 138,'C-F12',0
db 139,'M-F11',0
db 140,'M-F12',0
db 141,'C-Up Arrow',0
db 142,'C-Minus',0
db 143,'C-Five',0
db 144,'C-Plus',0
db 145,'C-Down Arrow',0
db 146,'C-Ins',0
db 147,'C-Del',0
db 148,'C-Tab',0
db 149,'C-Slash',0
db 150,'C-Asterisk',0
db 151,'M-Home',0
db 152,'M-Up Arrow',0
db 153,'M-Pg Up',0
; db 154,'154',0
db 155,'M-Left Arrow',0
; db 156,'156',0
db 157,'M-Right Arrow',0
; db 158,'158',0
db 159,'M-End',0
db 160,'M-Down Arrow',0
db 161,'M-Pg Dn',0
db 162,'M-Ins',0
db 163,'M-Del',0
db 164,'M-Slash',0
db 165,'M-Tab',0
db 166,'M-Return',0
db 167,'C- ',0
db 168,'M- ',0
; db 224,'Slash',0
; db 224,'Return',0
db 0,'Unknown',0
one_key_string db ?,0
ctrl_key_string db 'C-'
ctrl_key_char db ?,0
left_flag equ 1
right_flag equ 2
ctrl_flag equ 4
alt_flag equ 8
all_flags equ left_flag + right_flag + ctrl_flag + alt_flag
shift_flags db ?
bios_seg segment at 40h
org 17h
bios_shifts db ?
bios_seg ends
key_buffer label byte ;this is where we put the ASCII
db 26 dup(?) ; representation of the key.
extrn inversing: word ;if we're inverse videoing.
public color
color db 0fh ;xbbbifff bbb=background, ifff=fore.
control_color db 1fh ;attributes for control characters.
whitespc_color db 0fh ;attributes for whitespace characters.
font_8_table label byte
db 007h ;visi space
db 004h ;visi tab
db ? ;del
db ? ;eof
db ? ;visi newline
db 01ah ;right arrow
db ? ;random char.
db 01fh ;visible newline.
db 018h ;up arrow.
db 019h ;down arrow.
db 20h ;trailing space
ibm_cga db 0 ;=0 if we can write to screen anytime,
;=1 if we should wait for retrace.
have_ega db 0 ;=0 if we don't have an EGA.
scroll_bar db 0 ;nonzero if we have a scroll bar.
int_16_input db 0 ;function code for keyboard input
int_16_status db 1 ;function code for keyboard status
in_dv db 0 ;<>0 if we are running under DesqView.
data ends
code segment byte public
assume cs:code, ds:data, es:nothing
;all of the code in this segment is called with the above assumes.
break_flag db ?
their_1b dd ?
our_1b:
mov cs:break_flag,1
iret
public init_entry
init_entry:
push es ;get their C-break.
mov ax,351bh
int 21h
mov word ptr their_1b+0,bx
mov word ptr their_1b+2,es
pop es
push ds ;set our C-break.
mov ax,cs
mov ds,ax
mov dx,offset our_1b
mov ax,251bh
int 21h
pop ds
;
;Determine if Desqview is present.
;
mov cx,'DE'
mov dx,'SQ'
mov ax,2b01h
int 21h
cmp al,0ffh
je no_desqview
inc in_dv
no_desqview:
;
;Determine whether or not the BIOS supports extended keyboard functions.
;
push ds
mov ax,40h
mov ds,ax
mov al,ds:[96h] ;keyboard support byte.
pop ds
test al,10h
je init_entry_0 ;no - they don't have an extended kbd.
mov int_16_input,10h ;yes - use extended keyboard function codes.
mov int_16_status,11h
init_entry_0:
;
;Now set the video mode to one that we can use.
;
mov ah,15
int 10h ;get video state of the PC
mov screen_columns,40
mov num_screen_cols,40
cmp al,1 ;40 column text mode?
jbe init_entry_1 ;Yes, ok.
mov screen_columns,80
mov num_screen_cols,80
cmp al,3 ;Is screen CGA Text?
jbe init_entry_1 ;Yes, ok.
cmp al,7 ;Is screen MDA?
je init_entry_5 ;Yes, ok - but we can't have an EGA.
;
;Check to make sure there's memory at b800h. If there isn't, revert to
;video mode 3.
;
push ds
mov ax,0b800h
mov ds,ax
mov ax,ds:[0] ;save the original
not word ptr ds:[0] ;try to change the memory.
not ax ;change the original.
cmp ax,ds:[0] ;did they both change?
pushf
not ax ;restore the original contents.
mov ds:[0],ax
popf
pop ds
je init_entry_1 ;go if there's memory there.
mov ax,0*256 + 3 ;use 25x80 color if some strange mode.
int 10h
init_entry_1:
mov ax,1200h ;test for an EGA
mov bx,10h
mov cx,-1
int 10h
cmp cx,-1
je init_entry_2 ;no EGA.
mov have_ega,1 ;remember that we have an EGA.
push ds ;get the max scanlines.
xor ax,ax
mov ds,ax
mov al,ds:[484h]
mov ah,ds:[485h]
mov cl,ds:[44ah]
pop ds
mov screen_columns,cl ;remember how wide it is.
sub al,2 ;leave room for a status and minibuffer line.
mov max_screen_line,al
init_entry_2:
mov al,screen_columns
mov num_screen_cols,al
cmp swap_screen_flag,0 ;should we swap the screen?
je init_entry_4 ;no.
mov bh,0
mov ah,3 ;get cursor position
int 10h
mov old_cursor,dx
mov dl,max_screen_line ;copy the page zero to page one.
add dl,2
mov al,dl
; inc al
add al,dl
init_entry_3:
call move_line ;enter with dl=source, al=destination.
dec al
dec dl
jns init_entry_3
init_entry_5:
push es
mov dh,0
mov dl,max_screen_line
add dl,2
call get_video_ptr
mov ax,es:[di] ;get the attributes from the lower left.
pop es
mov fore_original,ah
and fore_original,0fh
mov cl,4 ;rotate the background to where we
shr ah,cl ; want it.
and ah,7
mov back_original,ah
clear_screen:
mov dh,0 ;clear the screen.
mov dl,max_screen_line
add dl,2
clear_screen_1:
call clear_to_eol ;enter with dl=row, dh=column.
dec dl
jns clear_screen_1
init_entry_4:
jmp adjust_for_bar
public uninit_exit
uninit_exit:
;called when exiting. May destroy any but seg-regs.
push ds ;restore C-break.
lds dx,their_1b
mov ax,251bh
int 21h
pop ds
cmp swap_screen_flag,0 ;should we swap the screen?
jne uninit_exit_4 ;yes.
ret ;no.
uninit_exit_4:
mov al,screen_columns ;restore the "correct" size.
mov num_screen_cols,al
mov ah,15
int 10h ;get video state of the PC
cmp al,7 ;don't restore the memory on an MDA
je uninit_exit_1 ; 'cuz it ain't there.
mov dx,old_cursor
mov bh,0
mov ah,2 ;set cursor position
int 10h
mov al,max_screen_line ;copy the page one to page zero.
add al,2
mov dl,al
add dl,dl
uninit_exit_3:
call move_line ;enter with dl=source, al=destination.
dec dl
dec al
jns uninit_exit_3
jmp short adjust_for_bar
uninit_exit_1:
mov dl,0
mov dh,max_screen_line
add dh,2
mov bh,0
mov ah,2 ;set cursor position
int 10h
call clear_screen
;fall through
;
adjust_for_bar:
;adjust the num_screen_cols for the scroll bar (if enabled).
cmp scroll_bar,0 ;have they enabled the scroll bar?
je adjust_for_bar_1 ;no.
dec num_screen_cols
adjust_for_bar_1:
ret
outreg macro port,value
mov al,port
out dx,al
inc dx
mov al,value
out dx,al
dec dx
endm
if 0
set_start_addr:
;given screen_start (the first text line on the screen), scan_row (the first
; scan row we're displaying), and bot_window, set the appropriate registers.
mov dx,03dah ;wait for vertical retrace.
cli ;no interrupts.
set_start_addr_h:
in al,dx ;Wait for horizontal retrace
test al,8 ; so will catch vertical
jz set_start_addr_h ; retrace at start.
set_start_addr_v:
in al,dx ;Wait for vertical retrace.
rcr al,1
jc set_start_addr_v
mov dx,03d4h
mov bx,screen_start ;screen_start is given in terms of
shr bx,1 ; bytes, but we need words.
outreg 0ch,bh ;the high byte of the starting address.
outreg 0dh,bl ;the low byte of the starting address.
outreg 08h,scan_row ;Preset row scan.
mov bx,bot_window
shl bh,1 ;put the bit in the right place.
shl bh,1
shl bh,1
shl bh,1
or bh,0fh ;assume that the rest are ones.
outreg 18h,bl ;set the low byte of line compare.
outreg 07h,bh ;set the overflow bits.
sti
ret
endif
public store_ibm_cga
store_ibm_cga:
cmp have_ega,0 ;do we have an EGA?
jne store_ibm_cga_1 ;yes - we know better than they do,
mov ibm_cga,al ; so ignore them.
store_ibm_cga_1:
ret
public store_scroll_bar
store_scroll_bar:
mov scroll_bar,al
or al,al ;are they enabling it?
mov al,screen_columns
je store_scroll_bar_1 ;no, don't leave room for it.
dec al
store_scroll_bar_1:
mov num_screen_cols,al
ret
public store_debug
store_debug:
if 1
cmp ibm_cga,0 ;don't do this on an IBM CGA.
jne store_debug_1
push ds
push es
push ax
mov ax,data
mov ds,ax
mov es,ax
mov dh,screen_columns
sub dh,2
mov dl,max_screen_line
inc dl
call get_video_ptr ;enter with dl=current row, dh=current column.
;return with es:di->character position.
pop ax
mov es:[di],al
mov es:[di+2],ah
pop es
pop ds
store_debug_1:
endif
ret
;this routine should check for a break character. Return cy if none,
; nc if we should break.
public check_breakchar
check_breakchar:
cmp cs:break_flag,0 ;test the break flag.
mov cs:break_flag,0 ;clear the break flag.
stc
je check_breakchar_1
clc
check_breakchar_1:
ret
public give_up_slice
give_up_slice:
cmp in_dv,0
je give_up_slice_1
push bx
push si
push bp
mov bx,1000h
int 15h
pop bp
pop si
pop bx
give_up_slice_1:
ret
public check_for_key
check_for_key:
;return zr,ax=0 if no key is waiting.
;return nz,ax=key if a key is waiting, but don't input the key yet.
mov ah,int_16_status ;check for a key.
int 16h
jne check_for_key_1 ;go if we got a key.
mov ax,0 ;return ax=0 if we didn't.
check_for_key_1:
ret
public get_key_value
get_key_value:
;exit with ax=keycode.
mov ah,int_16_input
int 16h
ret
public decode_key
decode_key:
;enter with ax=key value.
;exit with si,cx -> the key's name in ASCII.
mov di,offset key_buffer
cmp ax,0f9h ;one of the mouse buttons?
jb decode_key_7
cmp ax,0feh
ja decode_key_7
push ax
push ds
mov ax,bios_seg
mov ds,ax
assume ds:bios_seg
mov ah,bios_shifts
and ah,all_flags ;isolate the flags we're interested in.
pop ds
assume ds:data
mov shift_flags,ah
call decode_meta
call decode_ctrl
call decode_shift
pop ax
decode_key_7:
or al,al ;extended function key?
je decode_key_5
cmp ax,00e0h ;Did they enter e0 using the keypad?
je decode_key_6 ;yes -- it's a real key.
cmp al,0e0h
je decode_key_5
push ax ;now we look for ASCII keys that
mov si,offset key_others ; have dedicated keys.
call decode_search ;search for the scan code names.
pop ax
jne decode_key_2 ;go if we found it.
mov ah,al
mov si,offset key_names ;now search for the ASCII keys that
; we don't (or can't) represent.
call decode_search ;search for the literal names.
jne decode_key_1 ;copy it in.
mov al,ah
cmp al,' ' ;control char?
jae decode_key_6 ;no
add al,'`' ;yes - convert into letter.
mov ctrl_key_char,al
mov si,offset ctrl_key_string
cmp al,'z' ;control character > 'C-z'?
jbe decode_key_1 ;no.
sub ctrl_key_char,'`'-'@' ;yes - make it C-[, not C-{
jmp short decode_key_1
decode_key_2:
push si
mov si,offset key_special
mov ah,al ;now see if it's one of the ones we
call decode_search ; know are special.
pop ax
jne decode_key_1 ;yes - it is.
mov si,ax
jmp short decode_key_1
decode_key_6:
mov one_key_string,al
mov si,offset one_key_string
jmp short decode_key_1
decode_key_5:
mov si,offset key_table ;search for the extended functions.
call decode_search
decode_key_1:
lodsb ;copy to the next null.
stosb
or al,al
jne decode_key_1
dec di ;don't include the null.
mov si,offset key_buffer
mov cx,di
sub cx,si
ret
decode_ctrl:
test shift_flags,ctrl_flag
je decode_ctrl_1
mov ax,'C' + '-'*256
stosw
decode_ctrl_1:
ret
decode_shift:
test shift_flags,left_flag + right_flag
je decode_shift_1
mov ax,'S' + '-'*256
stosw
decode_shift_1:
ret
decode_meta:
test shift_flags,alt_flag
je decode_meta_1
mov ax,'M' + '-'*256
stosw
decode_meta_1:
ret
decode_search:
;enter with ah=key to search for, si->table.
;exit with al=key, nz if found, al=0, zr if not found.
lodsb
or al,al ;end of table?
je decode_search_2 ;yes - try shifted values.
cmp al,ah ;is this the key?
je decode_search_2 ;yes.
decode_search_1:
lodsb ;skip to the next null.
or al,al
jne decode_search_1
jmp decode_search
decode_search_2:
or al,al
ret
public ring_the_bell
ring_the_bell:
;enter with bx = first argument, cx = second argument.
or cx,cx
jne ring_the_bell_1
mov cx,1 ;defaults to duration of one.
ring_the_bell_1:
or bx,bx ;negative frequency?
jl vbell ;yes - they must want a visual bell.
;Beep procedure count values
;---------------------------
;To generate a given freqency note out of the speaker with the Beep procedure
;on the PC using Channel 2 of the 8253 timer, the channel 2 count register
;must be loaded with a value such that the 8253 input clock frequency
;(1.19318 MHz) divided by the count figure equals the audio frequency.
;enter with bx=count figure for frequency to be generated.
beep:
push cx
mov cx,1
call sleep
pop cx
mov al,0b6h ; Channel 2, LSB then MSB, Square Wave, Binary
out 43h,al ; Program 8253 command register
mov ax,bx ; Get the frequency to be generated
out 42h,al ; Load Channel 2 count register LSB
mov al,ah
out 42h,al ; Load Channel 2 count register MSB
in al,61h ; Read settings from 8255 PPI I/O Port "PB"
push ax ; Save original settings in AH
or al,3 ; Enable Timer Channel 2 & Speaker data
out 61h,al ; program the 8255 with new setting-speaker on
call sleep ; Wait for a while.
pop ax ; Get original 8255 Port "PB" settings
out 61h,al ; Reset port to original values-speaker off
ret
vbell:
push cx
mov cx,1 ;get syncronized with the timer
call sleep
call reverse
pop cx ;now wait that many seconds.
or cx,cx ;if zero duration, just wait one tick.
jne vbell_1
mov cx,1
vbell_1:
call sleep
reverse:
push di ; Save es,di
push es
call get_video_seg
mov ah,num_screen_cols ; Calc number of chars
mov al,max_screen_line
add al,2 ; the entire screen
mul ah
mov cx,ax
mov di,1 ; Offset to start at
rev1:
mov al,es:[di] ; Reverse the foreground/background
rol al,1
rol al,1
rol al,1
rol al,1
and al,77h
and byte ptr es:[di],not 77h
or es:[di],al
add di,2
loop rev1
pop es
pop di
ret
sleep:
;pause for cx 18ths.
push bx
push ds ; make ds = bios.
mov ax,40h
mov ds,ax
wait2:
mov bx,ds:[6ch] ; Get the current timer value.
wait1:
cmp bx,ds:[6ch] ; Did the timer value "tick"?
je wait1 ; No - keep waiting for a tick.
loop wait2 ; LOOP is first executed
pop ds
pop bx
ret
code ends
code segment byte public
assume cs:code, ds:nothing, es:data, ss:data
;all of the code in this segment is called with the above assumes.
public read_ibm_cga
read_ibm_cga:
mov al,ibm_cga
ret
public read_scroll_bar
read_scroll_bar:
mov al,scroll_bar
ret
public position_cursor
position_cursor:
;enter with dh=col (0...80), dl=row (0..max_screen_line)
;exit with cursor set to that position.
push bx
push dx
push si
push di
push bp
xchg dh,dl
mov bh,0
mov ah,2 ;set cursor position
int 10h
pop bp
pop di
pop si
pop dx
pop bx
ret
crt_status equ 3dah ; crt status port
;requires dx = crt_status. Destroys ax.
retrace_wait macro
local loop1,loop2
loop1:
in al,dx
shr al,1 ; display enabled?
jc loop1 ; yes, keep waiting
loop2:
in al,dx
shr al,1 ; now wait for it to go off
jnc loop2 ; so can have whole cycle
endm
public move_line
move_line:
;enter with dl=source row, al=destination row.
push ax
push bx
push cx
push dx
push si
push di
push bp
push ds
push es
push ax ;compute the source byte.
mov al,screen_columns
mul dl
shl ax,1
mov si,ax
pop ax
mov ah,screen_columns ;compute the destination byte.
mul ah
shl ax,1
mov di,ax
mov cx,word ptr num_screen_cols ;move the line.
call get_video_seg ;get the video card plane.
mov ds,ax
assume ds:nothing, es:nothing
cmp ibm_cga,0
je move_line_2
mov dx,crt_status ;load it only once.
move_line_1:
retrace_wait
lodsw ;get our char into bx.
mov bx,ax
retrace_wait
mov ax,bx
stosw
loop move_line_1
jmp short move_line_3
move_line_2:
rep movsw
move_line_3:
pop es
pop ds
assume ds:nothing, es:data
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
public read_chars
read_chars:
;enter with dl=source row, es:di -> destination bytes.
;exit with di incremented.
assume ds:nothing, es:nothing
push dx
mov al,screen_columns
mul dl
shl ax,1
mov si,ax
push ds
push es
mov cx,word ptr num_screen_cols ;read the line.
call get_video_seg ;get the video card plane.
mov ds,ax
pop es
assume ds:nothing, es:nothing
mov dx,crt_status ;load it only once.
read_line_1:
retrace_wait
lodsw ;get our char into bx.
stosb
loop read_line_1
pop ds
pop dx
ret
assume ds:nothing, es:data
public clear_to_eol
clear_to_eol:
;enter with dl=current row, dh=current column.
push bx
mov bl,num_screen_cols
call clear_count
pop bx
ret
public clear_count
clear_count:
;enter with dl=current row, dh=current column, bl=column to clear to.
push ax
push bx
push cx
push si
push di
push bp
push es
clear_count_0:
cmp dh,bl ;already past it?
jae clear_count_3 ;yes.
mov ah,color
mov al,' ' ;clear to the background color.
push ax
call get_video_ptr
assume ds:nothing, es:nothing
mov cl,bl ;compute the number of chars to clear.
sub cl,dh
mov ch,0
pop ax
cmp ibm_cga,0 ;slow refresh?
je clear_count_2
push dx
mov bx,ax ;retrace_wait destroys ax.
mov dx,crt_status ;load it only once.
clear_count_1:
retrace_wait
mov ax,bx
stosw
loop clear_count_1
pop dx
jmp short clear_count_3
clear_count_2:
rep stosw
clear_count_3:
pop es
assume ds:nothing, es:data
pop bp
pop di
pop si
pop cx
pop bx
pop ax
ret
get_video_ptr:
;enter with dl=current row, dh=current column.
;doesn't destroy bx.
;return with es:di->character position.
mov al,screen_columns ;compute the offset of the char.
mul dl
add al,dh
adc ah,0
shl ax,1
mov di,ax
get_video_seg:
;return with es,ax=video segment.
xor ax,ax
mov es,ax
mov ax,0b000h
cmp byte ptr es:[449h],7 ;MDA?
je get_video_seg_1 ;yes - we have the segment already.
mov ax,0b800h ;no - segment at b800h.
get_video_seg_1:
mov es,ax
mov ah,0feh ;let desqview change the segment.
int 10h
mov ax,es
ret
public xychrout
xychrout:
;enter with dh=col, dl=row, al=character to print, ah=font to print it in.
push ax ;save everything that we might need.
push bx
push cx
push dx
push di
push si
push es
push ds
mov bx,es
mov ds,bx
cmp dh,screen_columns ;past the right margin?
jae xychrout_3 ;yes - don't print.
cmp ah,0 ;font zero?
jne xychrout_5 ;no - print specially.
mov ah,color ;assume no inverse video
cmp al,0ffh ;print 255 specially
je xychrout_del
cmp al,20h ;is this a space or so?
jb xychrout_control ;print control chars specially.
jmp short xychrout_1
xychrout_del:
mov al,7fh-'@' ;show bold del.
xychrout_control:
mov ah,control_color
add al,'@'
jmp short xychrout_1
xychrout_5:
mov ah,whitespc_color
mov bx,offset font_8_table
sub al,4dh ;first character in font 8.
xlat
xychrout_1:
cmp inversing,0 ; check inversion flag
je no_invers ; skip inversion code
mov cl,4 ; we're inversing: so exchange
rol ah,cl ; fore & background color
and ah,7Fh ; avoid blinking background
no_invers:
mov bx,ax ;save the char in bx.
call get_video_ptr
assume ds:nothing, es:nothing
cmp ibm_cga,0 ;if we have an IBM CGA, we have to wait
je xychrout_4 ; for retrace, otherwise not.
mov dx,crt_status
retrace_wait
xychrout_4:
mov ax,bx
stosw
xychrout_3:
pop ds
pop es
assume ds:nothing, es:data
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
public hardware_roll_down
hardware_roll_down:
;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
; otherwise, exit with cy=1. The hardware roll must leave the last line
; on the screen as the last line.
;preserve bx.
cmp ibm_cga,0
je no_roll_down
push bx
push cx
push dx
mov ch,ah
mov cl,0
mov dh,al
mov dl,num_screen_cols
dec dl
mov bh,color
mov ax,701h
int 10h
pop dx
pop cx
pop bx
clc
ret
no_roll_down:
stc
ret
public hardware_roll_up
hardware_roll_up:
;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
; otherwise, exit with cy=1. The hardware roll must leave the last line
; on the screen as the last line.
;preserve bx.
cmp ibm_cga,0
je no_roll_up
push bx
push cx
push dx
mov ch,ah
mov cl,0
mov dh,al
mov dl,num_screen_cols
dec dl
mov bh,color
mov ax,601h
int 10h
pop dx
pop cx
pop bx
clc
ret
no_roll_up:
stc
ret
public set_screen_color
set_screen_color:
;enter with si -> list of colors (fore, back, control, whitespc)
mov cl,4
mov ah,[si+1] ;background doesn't change.
shl ah,cl
and ah,70h ;don't let them set blinking colors.
mov al,[si] ;compute the normal attributes.
or al,ah
mov color,al
mov al,[si+2] ;now the control attributes.
or al,ah
mov control_color,al
mov al,[si+3] ;now the whitespace attributes.
or al,ah
mov whitespc_color,al
ret
public pick_init, pick_on, pick_off, check_pick, get_pick_values
pick_init:
call mouse_exists
mov ax,0
int 33h
mov mouse_flag,al ;remember if the mouse exists.
mov mouse_buttons,bl ;remember the number of buttons.
mov ax,4 ;move the mouse to the upper right hand.
mov cx,635
mov dx,0
int 33h
mov ax,10 ;set text cursor (ignored on Z-100).
mov bx,0 ;software text cursor.
mov cx,77ffh ;screen mask
mov dx,7700h ;cursor mask
int 33h
mov al,max_screen_line ;compute the "number of scan lines"
add al,2
mul scan_lines_per_char
dec ax
;;; this used to be "dec dx", but that can't be right...
mov dx,ax ;set the "number of scan lines"
mov cx,0
mov ax,8
int 33h
mov al,8 ;we're assuming nine bits per char.
mul screen_columns
dec ax
mov dx,ax ;set the "number of bit columns"
mov cx,0
mov ax,7
int 33h
call check_pick ;ensure that there are no up or down
call check_pick ; events left.
call check_pick
call check_pick
call check_pick
call check_pick
ret
pick_on:
call mouse_exists
mov ax,1
int 33h
ret
pick_off:
call mouse_exists
mov ax,1 ;ensure that we work with MOUSEKEY.
int 33h
mov ax,2
int 33h
ret
check_pick:
;return nz and al=pick character. return zr if no pick.
call mouse_exists
push bx
push cx
push dx
cmp mouse_flag,0 ;inhibit mouse presses if it isn't there.
je check_pick_1
mov ax,5
mov bx,0 ;left button press
int 33h
mov ax,0feh
or bx,bx
jne check_pick_1
mov ax,5 ;right button press
mov bx,1
int 33h
mov ax,0fdh
or bx,bx
jne check_pick_1
mov ax,6 ;left button release
mov bx,0
int 33h
mov ax,0fch
or bx,bx
jne check_pick_1
mov ax,6 ;right button release
mov bx,1
int 33h
mov ax,0fbh
or bx,bx
jne check_pick_1
cmp mouse_buttons,2 ;do we have only two buttons?
je check_pick_1 ;yes - no pick.
mov ax,6 ;middle button release
mov bx,2
int 33h
mov ax,0f9h
or bx,bx
jne check_pick_1
mov ax,5 ;middle button press
mov bx,2
int 33h
mov ax,0fah
or bx,bx
jne check_pick_1
check_pick_1:
pop dx
pop cx
pop bx
ret
get_pick_values:
mov cx,0
mov dx,0
call mouse_exists
mov ax,3
int 33h
push cx ;save the x value.
mov ax,dx
div scan_lines_per_char
mov ah,0
push ax
call read_linesbefore
push ax
call read_newrow
pop bx
sub bx,ax ;bx=linesbefore - newrow.
pop dx
add dx,bx ;add y-value.
inc dx ;ax= y-value - newrow + linesbefore + 1.
pop ax ;compute the x-value.
push dx
mov cl,8
div cl
mov ah,0
inc ax
push ax ;add in firstcolumn.
call read_firstcolumn
pop cx
add cx,ax
pop dx
ret
extrn read_firstcolumn: near
extrn read_linesbefore: near
extrn read_newrow: near
;this routine returns from the routine that called it if the mouse is not
; installed.
mouse_exists:
push ds
xor ax,ax
mov ds,ax
mov ax,word ptr ds:[33h*4+2]
pop ds
cmp ax,0 ;any mouse interrupt at all?
je mouse_exists_2 ;no - no mouse.
cmp ax,40h ;is the mouse interrupt in the bios?
jne mouse_exists_1 ;no - must be a real mouse.
mouse_exists_2:
add sp,2
xor ax,ax
ret
mouse_exists_1:
ret
code ends
end